package chagine.core.util;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 多线程，带相同返回值
 *
 * @param <T>
 */
@Slf4j
public class ThreadTask<T> {

    /**
     * 默认线程数为核显的2倍
     */
    private static final int DEFAULT_THREAD_NUMBER = Runtime.getRuntime().availableProcessors() * 2;
    /**
     * 线程池
     */
    private ExecutorService executorService;
    /**
     * 任务列表
     */
    private List<Callable<T>> taskList;
    /**
     * 任务结果
     */
    private List<T> resultList;
    /**
     * 运行状态
     */
    private boolean runnableStatus;
    /**
     * 运行结束
     */
    private boolean runOver;

    /**
     * 创建任务线程数量
     */
    public ThreadTask() {
        this(DEFAULT_THREAD_NUMBER);
    }

    /**
     * 创建任务线程
     *
     * @param threadNumber 指定线程池数量
     */
    public ThreadTask(int threadNumber) {
        this.executorService = Executors.newFixedThreadPool(threadNumber);
        this.taskList = new ArrayList<>();
        this.runnableStatus = false;
        this.runOver = false;
    }

    /**
     * @return false 任务添加失败，任务已经禁止添加
     */
    public boolean addTask(Callable<T> task) {
        if (runOver) {
            return false;
        }
        if (runnableStatus) {
            return false;
        }
        taskList.add(task);
        return true;
    }

    /**
     * 运行任务，只运行一次
     */
    public List<T> runOrGetResult() throws InterruptedException, ExecutionException {
        if (runOver) {
            return resultList;
        }
        runnableStatus = true;
        try {
            List<Future<T>> futures = executorService.invokeAll(taskList);
            resultList = new ArrayList<>();
            for (Future<T> future : futures) {
                T t = future.get();
                resultList.add(t);
            }
            taskList.clear();
            runnableStatus = false;
            runOver = true;
            return resultList;
        } finally {
            executorService.shutdown();
        }
    }

}
